package jnpf.filter;

import cn.dev33.satoken.id.SaIdUtil;
import cn.hutool.extra.spring.SpringUtil;
import jnpf.base.UserInfo;
import jnpf.config.ConfigValueUtil;
import jnpf.consts.AuthConsts;
import jnpf.util.Constants;
import jnpf.util.UserProvider;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

/**
 * Dubbo过滤器 自动传递装载UserInfo
 */
@Activate(group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER}, order = 101)
public class MyDubboTokenFilter implements Filter {

    private static ConfigValueUtil configValueUtil;

    public MyDubboTokenFilter(){
        MyDubboTokenFilter.configValueUtil = SpringUtil.getBean(ConfigValueUtil.class);
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        UserInfo userInfo;
        Result result;
        //Provider端
        if(RpcContext.getContext().isProviderSide()){
            try {
                //设置本地认证信息
                userInfo = (UserInfo) RpcContext.getContext().getObjectAttachment(Constants.AUTHORIZATION);
                UserProvider.setLocalLoginUser(userInfo);
                if(configValueUtil.isEnableInnerAuth()) {
                    String innerToken = invocation.getAttachment(AuthConsts.INNER_TOKEN_KEY);
                    SaIdUtil.checkToken(innerToken);
                }
                result = invoker.invoke(invocation);
            }finally{
                //清除用户缓存
                UserProvider.clearLocalUser();
            }
        }else{
            //Consumer端
            //传递UserInfo
            userInfo = UserProvider.getUser();
            if(userInfo.getUserId() != null){
                invocation.setAttachment(Constants.AUTHORIZATION, userInfo);
            }
            if(configValueUtil.isEnableInnerAuth()) {
                invocation.setAttachment(AuthConsts.INNER_TOKEN_KEY, UserProvider.getInnerAuthToken());
            }
            result = invoker.invoke(invocation);
        }
        return result;
    }

}
